﻿
#ifdef _WIN32
#include <WinSock2.h>
#include <Windows.h>
#include <time.h>
#endif

#ifdef __unix__
#include <arpa/inet.h>
#endif

#ifdef _WIN32
#pragma comment(lib, "Packet.lib")
#pragma comment(lib, "wpcap.lib")
#pragma comment(lib, "ws2_32.lib")
#pragma warning(disable : 4996)
#pragma warning(disable : 4702)
#endif

#include <sstream>
#include <sys/prctl.h>
#include "netpcap.h"
#include "netpcap_file.h"
#include "netpcap_log.hpp"

#define NETPCAP_READTIMEOUT 1000 /*1秒超时返回*/
#define NETPCAP_READPKTNUMS 500  /*返回包处理数量*/
#define NETPCAP_IFMAXNUMS 32     /*抓包网卡规格*/

namespace secsmart_pcap
{

/**
 * @brief 简单的网络抓包处理
 * @param unsigned char* param           自身处理对象指针
 * @param const pcap_pkthdr* header      抓包头部信息
 * @param const unsigned char* pkt_data  抓包数据信息
 *
 * @return null
 */
void netpcap_worker::worker_handler(unsigned char *param, const pcap_pkthdr *header, const unsigned char *pkt_data)
{
    netpcap_worker *worker = (netpcap_worker *)param;
    worker->m_pkt_stat.rx_pkt_nums++;
    worker->m_pkt_stat.rx_pkt_bytes += header->caplen;

    if (worker->m_task_info_.fn_pf_handler != nullptr) {
        int ret;
        cap_pkt_t pcap_pkt;
        pcap_pkt.frame_data = pkt_data;
        pcap_pkt.frame_len = header->caplen;
        pcap_pkt.stream_len = header->len;
        pcap_pkt.ts = header->ts;
        pcap_pkt.link_type = worker->m_link_type_;
        ret = worker->m_task_info_.fn_pf_handler((void *)&pcap_pkt, (void *)worker->m_task_info_.fn_ctx);
        if (ret != 0) {
            worker->m_pkt_stat.tx_pkt_drops++;
        } else {
            worker->m_pkt_stat.tx_pkt_nums++;
            worker->m_pkt_stat.tx_pkt_bytes += pcap_pkt.frame_len;
        }
    }

    if (worker->m_task_info_.task_info.write_file) {
        worker->worker_write_pcapfile(header, pkt_data);
    }

    LOG_TRACE("netpcap_mgr worker handler: packetlen={}, datalen={}, task name:{}, ifname:{}", header->caplen,
              header->len, worker->m_task_info_.task_info.task_name, worker->m_task_info_.task_info.if_name);
}

/**
 * @brief 网络任务停止
 *
 * @return null
 */
void netpcap_worker::worker_set_stop()
{
    if (m_is_running_) {
        m_is_running_ = false;
        LOG_TRACE("netpcap_mgr worker set stop! taskName={}", m_task_info_.task_info.task_name);
    }
};

/**
 * @brief 网络任务停止
 *
 * @return null
 */
void netpcap_worker::worker_stop()
{
    worker_close_device();
    if (nullptr != m_task_info_.fn_pf_stoper) {
        m_task_info_.fn_pf_stoper(m_task_info_.fn_ctx);
    }

    LOG_TRACE("netpcap_mgr worker stop! taskName={}", m_task_info_.task_info.task_name);
};

/**
 * @brief close device
 *
 * @return 成功 true， 失败false;
 */
void netpcap_worker::worker_close_device()
{
    if (m_pcap_dumper_ != nullptr) {
        pcap_dump_flush(m_pcap_dumper_);
        pcap_dump_close(m_pcap_dumper_);
        m_pcap_dumper_ = nullptr;
    }

    if (m_dev_handle_ != nullptr) {
        pcap_breakloop(m_dev_handle_);
        pcap_close(m_dev_handle_);
        m_dev_handle_ = nullptr;
    }

    if (m_pcap_file_ != nullptr) {
        delete m_pcap_file_;
        m_pcap_file_ = nullptr;
    }
    m_is_running_ = false;
}

/**
 * @brief pcap 打开网卡
 *
 * @return 成功 true， 失败false;
 */
bool netpcap_worker::worker_open_device()
{
    char errbuf[PCAP_ERRBUF_SIZE] = {0};

    if ((m_dev_handle_ = pcap_open_live(m_task_info_.task_info.if_name.c_str(), // name of the device
                                        65536,                                  // portion of the packet to capture.
                                               // 65536 grants that the whole packet will be captured on all the MACs.
                                        1,                   // promiscuous mode (nonzero means promiscuous)
                                        NETPCAP_READTIMEOUT, // read timeout
                                        errbuf               // error buffer
                                        )) == NULL) {
        LOG_ERROR("unable to open the interface {}. err={},task name={}", m_task_info_.task_info.if_name,
                       std::string(errbuf), m_task_info_.task_info.task_name);
        return false;
    }

    m_link_type_ = pcap_datalink(m_dev_handle_);

    // 设置过滤条件
    worker_set_pcap_filter(m_task_info_.task_info.filter_string);

    return true;
}

/**
 * @brief pcap 打开抓包文件
 *
 * @return 成功 true， 失败false;
 */
bool netpcap_worker::worker_open_pcapfile()
{
    char errbuf[PCAP_ERRBUF_SIZE] = {0};

    if ((m_dev_handle_ = pcap_open_offline(m_task_info_.file_info.file_name.c_str(), errbuf)) == NULL) {
        LOG_ERROR("unable to open the file {}. err={},task name={}", m_task_info_.file_info.file_name,
                       std::string(errbuf), m_task_info_.task_info.task_name);
        return false;
    }

    m_link_type_ = pcap_datalink(m_dev_handle_);

    // 设置过滤条件
    worker_set_pcap_filter(m_task_info_.task_info.filter_string);

    return true;
}

/**
 * @brief pcap 保存抓包文件初始化,抓包文件保存目录当前目录/pcap/任务名_接口名
 *
 * @return 成功 true， 失败false;
 */
void netpcap_worker::worker_write_pcapfile_init()
{
    if (m_dev_handle_ == nullptr) {
        return;
    }

    m_pcap_file_ = new netpcap_file;
    if (m_task_info_.file_info.file_limits != 0) {
        m_pcap_file_->pcapfile_limits_nums(m_task_info_.file_info.file_limits);
    }

    m_pcap_file_->pcapfile_set_dir_path(m_task_info_.file_info.dir);
    m_pcap_file_->pcapfile_set_file_name(m_task_info_.file_info.file_name);

    std::string file_path = m_pcap_file_->pcapfile_open_new_file();
    m_pcap_dumper_ = pcap_dump_open(m_dev_handle_, file_path.c_str());
    if (m_pcap_dumper_ == nullptr) {
        LOG_ERROR("failed call pcap_dump_open():{}, task name={} file path={}",
                       std::string(pcap_geterr(m_dev_handle_)), m_task_info_.task_info.task_name, file_path);
        return;
    }
}

/**
 * @brief 将报文写入文件
 *
 * @return 成功 true， 失败false;
 */
void netpcap_worker::worker_write_pcapfile(const pcap_pkthdr *header, const unsigned char *pkt_data)
{
    if (m_pcap_dumper_ == nullptr || m_dev_handle_ == nullptr) {
        return;
    }

    // 抓包写文件
    pcap_dump((u_char *)m_pcap_dumper_, header, pkt_data);
    m_pcap_file_->pcapfile_nums_update();
    if (m_pcap_file_->pcapfile_nums_get() >= m_pcap_file_->pcapfile_limits_get()) { // 当前文件写满了，需要新开一个文件
        // 关闭当前pcap dumper
        pcap_dump_flush(m_pcap_dumper_);
        pcap_dump_close(m_pcap_dumper_);
        m_pcap_dumper_ = nullptr;

        // 生成一个新的文件名, pcap dumper关联新的文件
        std::string file_path = m_pcap_file_->pcapfile_open_new_file();
        m_pcap_dumper_ = pcap_dump_open(m_dev_handle_, file_path.c_str());
        if (m_pcap_dumper_ == nullptr) {
            LOG_ERROR("failed call pcap_dump_open():{}, filename={}", std::string(pcap_geterr(m_dev_handle_)),
                           file_path);
            return;
        }
    }
}

void netpcap_worker::worker_set_pcap_filter(const std::string &filter_string)
{
    char errbuf[PCAP_ERRBUF_SIZE] = {0};
    bpf_u_int32 ipaddr, netmask = 0;
    struct bpf_program bpfcode;

    if (m_dev_handle_ == nullptr) {
        return;
    }

    // 获取接口网络掩码,获取使用使用默认值0
    if (!m_task_info_.task_info.read_file) {
        if (pcap_lookupnet(m_task_info_.task_info.if_name.c_str(), &ipaddr, &netmask, errbuf) == -1) {
            LOG_ERROR("failed call pcap_lookupnet(): {},device name:{}", errbuf, m_task_info_.task_info.if_name);
        }
    }

    if (pcap_compile(m_dev_handle_, &bpfcode, filter_string.c_str(), 1, netmask) < 0) {
        LOG_ERROR("unable to compile the packet filter:{}, task name={}", filter_string,
                       m_task_info_.task_info.task_name);
        return;
    }

    int ret = pcap_setfilter(m_dev_handle_, &bpfcode);
    if (ret < 0) {
        LOG_ERROR("failed call pcap_setfilter():({},{}), filter string={} task name={}", ret,
                       std::string(pcap_geterr(m_dev_handle_)), filter_string, m_task_info_.task_info.task_name);
        return;
    }
}

void netpcap_worker::worker_clean_stat()
{
    m_pkt_stat.rx_pkt_bytes = 0;
    m_pkt_stat.rx_pkt_nums = 0;
    m_pkt_stat.rx_pkt_drops = 0;
    m_pkt_stat.tx_pkt_nums = 0;
    m_pkt_stat.tx_pkt_bytes = 0;
    m_pkt_stat.tx_pkt_drops = 0;
}

void netpcap_worker::worker_get_stat(pcap_pkt_stat_t *pkt_stat, pcap_stat *dev_stat)
{
    if (pkt_stat == nullptr || dev_stat == nullptr) {
        return;
    }

    memset(pkt_stat, 0, sizeof(pcap_pkt_stat_t)); // 初始为0
    memset(dev_stat, 0, sizeof(struct pcap_stat));

    if (m_dev_handle_ != nullptr) {
        (void)pcap_stats(m_dev_handle_, dev_stat);
    }

    *pkt_stat = m_pkt_stat;
}

/**
 * @brief 线程执行主任务
 *
 * @return null
 */
bool netpcap_worker::worker_init()
{
    // 获取thread id
    std::ostringstream ss;
    ss << std::this_thread::get_id();
    std::string threadId = ss.str();

    LOG_INFO("Pcap worker start running...task name : {}, threadid:{}", m_task_info_.task_info.task_name,
                    threadId);
    m_task_info_.task_info.task_thid = threadId;

    if (m_task_info_.task_info.read_file) { // 抓包回放,从文件读取报文
        if (!worker_open_pcapfile()) {
            return false;
        }
    } else if (!worker_open_device()) { // 网口抓包
        return false;
    }

    if (m_task_info_.task_info.write_file) { // 抓包写文件
        worker_write_pcapfile_init();
    }

    worker_clean_stat();

    return true;
}

/**
 * @brief 线程执行主任务
 *
 * @return null
 */
void netpcap_worker::worker_run()
{
    (void)prctl(PR_SET_NAME, m_task_info_.task_info.task_name.c_str());

    LOG_TRACE("pcap task worker start run, task name={},ifname:{},filter:{}", m_task_info_.task_info.task_name,
                    m_task_info_.task_info.if_name, m_task_info_.task_info.filter_string);

    if (nullptr == this) {
        LOG_ERROR("pcap worker object THIS is null, start worker failed.");
        return;
    }

    if (!worker_init()) {
        m_is_running_ = false;
        LOG_ERROR("pcap worker init failed, task end.");
        return;
    }

    m_is_running_ = true;
    // 抓包报文处理
    while (m_is_running_) {
        int ret = pcap_dispatch(m_dev_handle_, NETPCAP_READPKTNUMS, worker_handler, (unsigned char *)this);
        if (ret == 0 && m_task_info_.task_info.read_file) {
            m_is_running_ = false;
            LOG_TRACE("read pcapfile {} done, task name={}", m_task_info_.file_info.file_name,
                            m_task_info_.task_info.task_name);
            break;
        }
        if (ret < 0) {
            LOG_ERROR("failed on pcap dispatch, error_return:{},task name={}", ret,
                           m_task_info_.task_info.task_name);
            if (m_task_info_.task_info.read_file) {
                m_is_running_ = false;
                break;
            }
            worker_close_device();
            std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // 等待一秒后重新抓包
            worker_open_device();
        }
    }

    // 结束worker线程
    worker_stop();

    LOG_TRACE("pcap task worker has been [END], task name={},ifname:{},filter:{}",
                    m_task_info_.task_info.task_name, m_task_info_.task_info.if_name,
                    m_task_info_.task_info.filter_string);
    return;
}

/********************************************************/
/********************************************************/
/********************************************************/
/**
 * @brief 日志初始化
 * @param mlogger_sptr mlogSptr          日志输出对象,符合基类定义的规范即可
 *
 * @return bool
 */
bool netpcap_mgr::init(spdlogger_sptr logger)
{
    if (nullptr == logger) { // 如果没有传logger，则日志记到进程所在的目录下
        spdlogger_sptr spd_logger = std::make_shared<Spdlogger>();
        std::string log_path;
        std::string app_dir;
        pcap_app_dir_get(app_dir);
        log_path = app_dir + "netpcap_" + std::to_string(getpid()) + ".log";
        spd_logger->init(log_path);
        NETPCAP_LOG_INIT(spd_logger);
    } else {
        NETPCAP_LOG_INIT(logger);
    }

    NETPCAP_LOG_SETLEVEL(level::logger_level::info, true);
    LOG_TRACE("log init success.");
    return true;
}

/**
 * @brief 日志控制接口
 * @param std::int32_t level     日志级别
 * @param bool funcEnable        函数输出
 * @return bool
 */
bool netpcap_mgr::log_ctrl(std::uint32_t level, bool funcEnable)
{
    NETPCAP_LOG_SETLEVEL(level, funcEnable);
    LOG_TRACE("Log ctrl: level={}, funcIsTrace={}", level, funcEnable);
    return true;
}

/**
 * @brief 获取当前日志模块的级别
 * @return module_level
 */
std::uint32_t netpcap_mgr::log_get_module_level() { return NETPCAP_LOG_GET_LEVEL(); }

/**
 * @brief 模块资源回收函数
 * @return module_level
 */
void netpcap_mgr::uninit()
{
    pcap_task_stop_all();
    LOG_TRACE("uninit success.");
}

/**
 * @brief 获取当前设备的网卡列表
 * @param std::vector<std::string>& devLists     获取设备名称列表
 * @return bool
 */
bool netpcap_mgr::pcap_ifnames_get(std::vector<std::string> &devLists)
{
    pcap_if_t *alldevs; // 所有网卡设备保存
    pcap_if_t *dev;     // 用于遍历的指针
    int index = 0;
    char errbuf[PCAP_ERRBUF_SIZE] = {0};

    LOG_TRACE("pcap get ifname list.");
#if _WIN32
    /* 获取本地机器设备列表 */
    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) != -1) {
        /* 打印网卡信息列表 */
        for (dev = alldevs; dev != NULL; dev = dev->next) {
            if (dev->description) {
                LOG_TRACE("Device id:{} --> eth_desc:{}, eth_name:{}", index, dev->description, dev->name);
                devLists.push_back(dev->name);
                ++index;
            }
        }
    }
#else
    if (pcap_findalldevs(&alldevs, errbuf) == -1) {
        LOG_ERROR("pcap worker find devs failed, err:{}", errbuf);
        return false;
    }

    for (dev = alldevs; dev; dev = dev->next) {
        if (dev->name) {
            LOG_TRACE("Device id:{} --> eth_name:{}", index, dev->name);
            devLists.push_back(dev->name);
            ++index;
        }
    }
#endif
    /* 不再需要设备列表了，释放它 */
    pcap_freealldevs(alldevs);
    LOG_TRACE("device adapter nums={}", index);
    return true;
}

/**
 * @brief 获取当前设备的网卡信息
 * @param std::vector<ifinfo_sptr>& ifLists  设备列表信息
 * @return bool
 */
bool netpcap_mgr::pcap_ifinfos_get(std::vector<ifinfo_sptr> &ifLists)
{
    pcap_if_t *alldevs;
    pcap_if_t *dev;
    std::uint32_t index = 0;
    char errbuf[PCAP_ERRBUF_SIZE] = {0};

    if (ifLists.size() == 0)
        ifLists.resize(NETPCAP_IFMAXNUMS);

    LOG_TRACE("pcap get ifinfos, iflistSize={}", ifLists.size());

#if _WIN32
    /* 获取本地机器设备列表 */
    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) != -1) {
        /* 打印网卡信息列表, dev会存在null的情况 */
        for (dev = alldevs; dev != NULL; dev = dev->next) {
            ifinfo_sptr if_info_sptr = std::make_shared<if_info_s>();
            if (dev) {
                LOG_TRACE("Device id:{} --> eth_desc:{}, eth_name:{}", index, dev->description, dev->name);
                if_info_sptr->ifindex = index;
                if_info_sptr->ifname = dev->name;
                if_info_sptr->ifdesc = dev->description;
                ifLists.push_back(if_info_sptr);
                ++index;
            }
        }
    }
#else
    if (pcap_findalldevs(&alldevs, errbuf) == -1) {
        LOG_ERROR("pcap worker find devs failed, err:{}", errbuf);
        return false;
    }

    for (dev = alldevs; dev != nullptr; dev = dev->next) {
        ifinfo_sptr if_info_sptr = std::make_shared<if_info_s>();
        if (dev->name) {
            LOG_TRACE("Device id:{} --> eth_name:{}", index, dev->name);
            if_info_sptr->ifindex = index;
            if_info_sptr->ifname = dev->name;
            ifLists.push_back(if_info_sptr);
            ++index;
        } else
            LOG_ERROR("pcap find devs is nullptr.");
    }
#endif
    /* 不再需要设备列表了，释放它 */
    pcap_freealldevs(alldevs);

    LOG_TRACE("device adapter nums={}", index);
    return true;
}

/**
 * @brief 设备网络地址查询
 * @param const std::string& device  设备名称
 * @param std::string& netaddr       网络地址
 *
 * @return bool
 */
bool netpcap_mgr::pcap_device_netaddr_lookup(const std::string &device, std::string &netaddr)
{
    struct in_addr addr;
    bpf_u_int32 ip, mask;
    char errbuf[PCAP_ERRBUF_SIZE] = {0};

    if (pcap_lookupnet(device.c_str(), &ip, &mask, errbuf) == -1) {
        LOG_ERROR("failed call pcap_lookupnet(): {},device:{}", errbuf, device);
        return false;
    }

    char tmp[32] = {0};
    addr.s_addr = ip;
    strncpy(tmp, inet_ntoa(addr), sizeof(tmp));
    netaddr = std::string(tmp);

    LOG_TRACE("device:{}, net:{}", device, netaddr);

    return true;
}

/**
 * @brief 获取当前的app目录
 * @param std::string &dir  当前app所在的目录
 *
 * @return void
 */
void netpcap_mgr::pcap_app_dir_get(std::string &dir)
{
    pcapfile_sptr pcapfile_ptr = std::make_shared<netpcap_file>();
    dir = pcapfile_ptr->pcapfile_get_app_dir();
}

/**
 * @brief 用户自定义任务抓包
 * @param cap_task_t& capTasker          该抓包任务信息
 * @param cap_file_info_t& fileInfo      是否写文件相关信息，如果配置文件路径，则直接启动文件存储任务
 *
 * @return void
 */
bool netpcap_mgr::pcap_task_start(cap_task_t &capTasker)
{
    cap_task_info_t task_info;

    /*判断相同任务是否已存在*/
    if (true == task_map_query(capTasker.task_info.task_name, task_info)) {
        LOG_ERROR("pcap worker task start failed. task has exist. taskName:{},ifName:{},fliter:{}",
                       capTasker.task_info.task_name, task_info.if_name, task_info.filter_string);
        return false;
    }

    /*启动抓包任务*/
    pcapworker_sptr worker_sptr = std::make_shared<netpcap_worker>();
    worker_sptr->m_task_info_ = capTasker;
    std::shared_ptr<std::thread> threadPtr(
        new std::thread([worker_sptr] { worker_sptr->worker_run(); })); // Lambda表达式
    worker_sptr->m_thread_sptr_ = threadPtr;
    if (!worker_sptr->m_thread_sptr_->joinable()) {
        LOG_ERROR("pcap worker run failed. taskName:{}", capTasker.task_info.task_name);
        return false;
    }

    /*加入任务map管理列表*/
    if (false == task_map_add(capTasker.task_info.task_name, worker_sptr)) {
        worker_sptr->worker_stop();
        threadPtr->join();
        LOG_ERROR("pcap worker add failed. taskName:{}", capTasker.task_info.task_name);
        return false;
    }

    LOG_INFO("pcap worker start success. task name:{}", capTasker.task_info.task_name);
    return true;
}

/**
 * @brief 用户自定义任务抓包, 任务会阻塞, 等待所有文件完成
 * @param const std::string& filePath,  回放包绝对路径,依次进行包回放,当前仅回放".pcap"后缀
 * @param cap_task_t& pcapTasker,       并发任务处理回调
 *
 * @return void
 */
bool netpcap_mgr::pcap_task_start_replay(cap_task_t &pcapTasker)
{
    std::vector<std::string> files_vector;
    std::list<pcapworker_sptr> task_list;
    /*回放包自动结束*/
    pcapfile_sptr pcapfile_ptr = std::make_shared<netpcap_file>();
    if (pcapTasker.file_info.dir.length() != 0) {
        LOG_TRACE("pcap replay file directory {}", pcapTasker.file_info.dir);
        if (false == pcapfile_ptr->pcapfile_dir_get(pcapTasker.file_info.dir, files_vector)) {
            LOG_ERROR("pcap worker add failed. dirPath:{}", pcapTasker.file_info.dir);
            return false;
        }
    } else if (pcapTasker.file_info.file_name.length() != 0){
        LOG_TRACE("pcap replay file {}", pcapTasker.file_info.file_name);
        files_vector.push_back(pcapTasker.file_info.file_name);
    }

    if (nullptr == pcapTasker.fn_pf_handler) {
        LOG_ERROR("pcap worker handler is null.");
        return false;
    }

    for (auto filetmp : files_vector) {
        LOG_TRACE("pcap start task to replay cap file {}", filetmp);
        pcapworker_sptr worker_sptr = std::make_shared<netpcap_worker>();
        worker_sptr->m_task_info_.file_info.dir = pcapTasker.file_info.dir;
        worker_sptr->m_task_info_.file_info.file_name = filetmp;
        worker_sptr->m_task_info_.file_info.file_limits = 0;
        worker_sptr->m_task_info_.task_info.task_name = pcapTasker.task_info.task_name;
        worker_sptr->m_task_info_.task_info.read_file = true;
        worker_sptr->m_task_info_.fn_pf_handler = pcapTasker.fn_pf_handler;
        worker_sptr->m_task_info_.fn_pf_stoper = pcapTasker.fn_pf_stoper;
        worker_sptr->m_task_info_.fn_ctx = pcapTasker.fn_ctx;

        std::shared_ptr<std::thread> threadPtr(new std::thread([worker_sptr] { worker_sptr->worker_run(); }));
        worker_sptr->m_thread_sptr_ = threadPtr;

        /*加入任务map管理列表*/
        (void)task_map_add(pcapTasker.task_info.task_name, worker_sptr);

        if (!worker_sptr->m_thread_sptr_->joinable()) {
            LOG_INFO("pcap worker run end. file:{}", filetmp);
            continue;
        } else {
            /*单任务阻塞，等待结束*/
            threadPtr->join();
        }

        task_map_del(pcapTasker.task_info.task_name);
    }

    return true;
}

/**
 * @brief 用户任务列表
 * @param std::vector<std::string>& taskList, 任务名称列表获取
 *
 * @return void
 */
bool netpcap_mgr::pcap_task_list(std::vector<std::string> &taskList)
{
    pcapworker_sptr worker_sptr = nullptr;
    {
        std::lock_guard<std::mutex> lock(m_task_map_lock_);
        for (auto itemor = m_task_map_.begin(); itemor != m_task_map_.end(); ++itemor) {
            worker_sptr = itemor->second;
            taskList.push_back(worker_sptr->m_task_info_.task_info.task_name);
            LOG_TRACE("pcap task found success. taskName={}", worker_sptr->m_task_info_.task_info.task_name);
            return true;
        }
    }

    return false;
}

/**
 * @brief 用户任务信息获取
 * @param const std::string& taskName,   任务名称
 * @param const cap_task_info_t& state,  接口状态
 *
 * @return void
 */
bool netpcap_mgr::pcap_task_query(const std::string &taskName, cap_task_info_t &state)
{
    bool ret = task_map_query(taskName, state);

    if (false == ret) {
        LOG_ERROR("task name get state failed ,task name={}", taskName);
        return false;
    }

    return true;
}

/**
 * @brief 停止单个抓包任务
 *
 * @return void
 */
bool netpcap_mgr::pcap_task_stop(const std::string &taskName)
{
    if (taskName == "") {
        LOG_ERROR("task name has empty.");
        return false;
    }

    return task_map_del(taskName);
}

/**
 * @brief 停止所有抓包任务
 *
 * @return void
 */
bool netpcap_mgr::pcap_task_stop_all()
{
    (void)task_map_clear();
    return true;
}

/**
 * @brief 获取特定任务的报文统计
 *
 * @return void
 */
void netpcap_mgr::pcap_task_get_stat(const std::string &taskName, pcap_pkt_stat_t &pkt_stat, pcap_stat &dev_stat)
{
    std::lock_guard<std::mutex> lock(m_task_map_lock_);
    auto itemor = m_task_map_.find(taskName);
    if (itemor != m_task_map_.end()) {
        pcapworker_sptr worker_sptr = itemor->second;
        if (nullptr != worker_sptr->m_thread_sptr_) {
            worker_sptr->worker_get_stat(&pkt_stat, &dev_stat);
        }
    }
}

/**
 * @brief 获取所有任务的报文统计
 *
 * @return void
 */
void netpcap_mgr::pcap_task_get_stat_all(pcap_pkt_stat_t &pkt_stat, pcap_stat &dev_stat)
{
    pcapworker_sptr worker_sptr = nullptr;
    memset(&pkt_stat, 0, sizeof(pkt_stat)); // 初始为0
    memset(&dev_stat, 0, sizeof(dev_stat));

    std::lock_guard<std::mutex> lock(m_task_map_lock_);
    for (auto it = m_task_map_.begin(); it != m_task_map_.end(); it++) {
        worker_sptr = it->second;
        if (nullptr != worker_sptr->m_thread_sptr_) {
            pcap_stat dev;
            pcap_pkt_stat_t pkt;
            worker_sptr->worker_get_stat(&pkt, &dev);

            pkt_stat.rx_pkt_bytes += pkt.rx_pkt_bytes;
            pkt_stat.rx_pkt_nums += pkt.rx_pkt_nums;
            pkt_stat.rx_pkt_drops += pkt.rx_pkt_drops;
            pkt_stat.tx_pkt_bytes += pkt.tx_pkt_bytes;
            pkt_stat.tx_pkt_nums += pkt.tx_pkt_nums;

            dev_stat.ps_drop += dev.ps_drop;
            dev_stat.ps_ifdrop += dev.ps_ifdrop;
            dev_stat.ps_recv += dev.ps_recv;
        }
    }
}

void netpcap_mgr::pcap_task_set_filter(const std::string& task_name, const std::string &filter_string)
{
    std::lock_guard<std::mutex> lock(m_task_map_lock_);
    auto it = m_task_map_.find(task_name);
    if (it != m_task_map_.end()) {
        pcapworker_sptr worker_sptr = it->second;
        if (nullptr != worker_sptr->m_thread_sptr_) {
            worker_sptr->worker_set_pcap_filter(filter_string);
        }
    }
}

/**
 * @brief 管理任务添加
 * @param const std::string& taskName, 任务名称
 * @param networker_sptr workerSptr,   工作线程
 *
 * @return void
 */
bool netpcap_mgr::task_map_add(const std::string &taskName, pcapworker_sptr workerSptr)
{
    if (nullptr == workerSptr) {
        LOG_ERROR("failed the networker shared ptr. taskName:{}", taskName);
        return false;
    }

    {
        std::lock_guard<std::mutex> lock(m_task_map_lock_);
        if (m_task_map_.find(taskName) == m_task_map_.end()) {
            m_task_map_.insert(std::make_pair(taskName, workerSptr));
        } else {
            LOG_ERROR("pcap task has been existed. taskName={}", taskName);
            return false;
        }
    }

    LOG_TRACE("pcap task name:{} add map success", taskName);
    return true;
}

/**
 * @brief 管理任务删除
 * @param const std::string& taskName, 任务名称
 *
 * @return void
 */
bool netpcap_mgr::task_map_del(const std::string &taskName)
{
    pcapworker_sptr worker_sptr = nullptr;
    {
        std::lock_guard<std::mutex> lock(m_task_map_lock_);
        auto itemor = m_task_map_.find(taskName);
        if (itemor != m_task_map_.end()) {
            worker_sptr = itemor->second;
            worker_sptr->worker_set_stop();
            if (worker_sptr->m_thread_sptr_) {
                std::ostringstream ss;
                ss << worker_sptr->m_thread_sptr_->get_id();
                std::string threadId = ss.str();

                /*线程任务分离*/
                if (worker_sptr->m_thread_sptr_->joinable()) {
                    worker_sptr->m_thread_sptr_->join();
                    LOG_TRACE("pcap worker join success. thread id:{}", threadId);
                }
                LOG_TRACE("pcap task del map success. taskName={},thid={}", taskName, threadId);
            } else {
                LOG_CRITICAL("pcap task thread error. task name:{} ", taskName);
            }
            m_task_map_.erase(itemor);

            return true;
        }
    }

    LOG_ERROR("pcap task del map not found. task name:{} ", taskName);
    return false;
}

/**
 * @brief 管理任务查询
 * @param const std::string& taskName,   任务名称
 * @param std::string& ifName,           获取的接口名称
 * @param std::uint32_t &isRunning,      获取的运行状态
 *
 * @return void
 */
bool netpcap_mgr::task_map_query(const std::string &taskName, cap_task_info_t &taskInfo)
{
    pcapworker_sptr worker_sptr = nullptr;
    {
        std::lock_guard<std::mutex> lock(m_task_map_lock_);
        auto itemor = m_task_map_.find(taskName);
        if (itemor != m_task_map_.end()) {
            worker_sptr = itemor->second;
            if (nullptr != worker_sptr->m_thread_sptr_) {
                std::ostringstream ss;
                ss << worker_sptr->m_thread_sptr_->get_id();
                std::string threadId = ss.str();
                taskInfo.is_running = worker_sptr->m_is_running_;
                taskInfo.if_name = worker_sptr->m_task_info_.task_info.if_name;
                taskInfo.filter_string = worker_sptr->m_task_info_.task_info.filter_string;
                LOG_TRACE("pcap task found success. taskName={},thid={}", taskName, threadId);
            } else {
                LOG_CRITICAL("pcap task thread error. task name:{} ", taskName);
            }
            return true;
        }
    }

    LOG_TRACE("pcap task has not found. taskName={}", taskName);
    return false;
}

/**
 * @brief 清空所有抓包任务
 *
 * @return void
 */
bool netpcap_mgr::task_map_clear()
{
    {
        std::lock_guard<std::mutex> lock(m_task_map_lock_);
        std::for_each(m_task_map_.begin(), m_task_map_.end(),
                      [&](const std::pair<std::string, std::shared_ptr<netpcap_worker>> &itemor) {
                          itemor.second->worker_set_stop();
                          if (nullptr != itemor.second->m_thread_sptr_) {
                              std::ostringstream ss;
                              ss << itemor.second->m_thread_sptr_->get_id();
                              std::string threadId = ss.str();
                              if (itemor.second->m_thread_sptr_) {
                                  /*线程任务分离*/
                                  if (itemor.second->m_thread_sptr_->joinable()) {
                                      itemor.second->m_thread_sptr_->join();
                                      LOG_TRACE("pcap worker join success. thread id:{}", threadId);
                                  }
                              }
                              LOG_TRACE("pcap task clear. taskName={},thid={}",
                                       itemor.second->m_task_info_.task_info.task_name, threadId);
                          }
                      });

        m_task_map_.clear();
    }
    return true;
}

} // namespace secsmart_pcap
